﻿using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace WebAPI.Filters
{
    /// <summary>
    /// 限制特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
    public class AccessLimitAttribute : ActionFilterAttribute
    {
        private Stopwatch timer;

        private readonly int userLimitSecond = 3;

        private readonly long userLimitTimes = 50;

        private readonly int visitLimitSecond = 3;

        private readonly long visitLimitTimes = 10;

        /// <summary>
        /// Action调用之前运行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // 获取用户ID
            var userId = filterContext.HttpContext.Request.Headers["auth"];
            var controller = filterContext.Controller.ToString();
            //action = filterContext.ActionDescriptor.ToString();
            var action = filterContext.RouteData.Values["action"].ToString();
            
            RedisHelper.Initialization(new CSRedis.CSRedisClient("127.0.0.1:6379,defaultDatabase=0"));

            // 1.限制请求人数
            var userLimitKey = controller + "-" + action;
            if (!RedisHelper.Exists(userLimitKey))
            {
                RedisHelper.SAdd(userLimitKey, userId);
                RedisHelper.Expire(userLimitKey, userLimitSecond);
            }
            else
            {
                RedisHelper.SAdd(userLimitKey, userId);
                var size = RedisHelper.SCard(userLimitKey);
                if (size > userLimitTimes)
                {
                    filterContext.Result = new ContentResult { Content = "{\"flag\": 2,\"message\": \"请求人数过多,请稍后再试\" }" };
                    return;
                }
            }

            // 2.限制请求次数
            var key = controller + "/" + action + ":" + userId;
            if (!RedisHelper.Exists(key))
            {
                RedisHelper.HIncrBy(key, "user", 1);
                RedisHelper.Expire(key, visitLimitSecond);
            } else
            {
                long times = RedisHelper.HIncrBy(key, "user", 1);
                if (times > visitLimitTimes)
                {
                    filterContext.Result = new ContentResult { Content = "{\"flag\": 2,\"message\": \"请勿频繁操作\" }" };
                    return;
                }
            }

            // 3.记录请求时间
            timer = Stopwatch.StartNew();
        }

        /// <summary>
        /// Action调用之后运行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            timer.Stop();
            if (timer.Elapsed.TotalSeconds > 3)
            {
                // 记录日志
                Debug.WriteLine($"方法执行时间：{timer.Elapsed.TotalSeconds:F6}");
            }
        }
    }
}